#include "recepkgmanage.h"

RecePkgManage::RecePkgManage(QObject *parent)
{
    init();
}

void RecePkgManage::init()
{
    qDebug() << "RecePkgManage init----------------------------------------------------------------->";
    hadReceCount = 0;
    pkgCount = 0;
    recePkgStartNum = 0;
    recePkgEndNum = 0;
    startPos = 0;
    endPos = 0;
}

/*******************************************
  功能：添加收到的包编号
  参数：
  返回值：
  ******************************************/
bool RecePkgManage::addRecePkg(const int pkgNum, const qint64 position)
{
//    qDebug() << "addRecePkg===========>" << pkgNum << position << recePkgStartNum << pkgCount << unRecePkgList.count();

    //添加包编号思路：
    //将所有包分一个大的区间，首先是所有包都未收到，即从1~pkgCount这个是未收到的开始区间
    //然后每次收到一个包就添加进来，重新添加一个小区间 recePkgStartNum~recePkgEndNum，
    //因为包是顺序发送的，所以每次加1，逐步扩大收到包的区间，如果突然包编号不是以1增加，那么证明开始有
    //包丢失或者混乱，那么从未收到包的区间中删除已经收到包的区间，逐渐下去，直到完成
    if (pkgNum < 0)
    {
        return false;
    } else if (pkgCount <= 0 || unRecePkgList.count() == 0)
    {
        return false;
    }

    endPos = position;
    if (recePkgStartNum == 0)
    {
        recePkgStartNum = pkgNum;
        recePkgEndNum = pkgNum;
        startPos = position;
    } else {
        if (pkgNum - recePkgEndNum > 1)
        {
            FilePkgStruct filePkgStruct;
            filePkgStruct.start = recePkgStartNum;
            filePkgStruct.startPos = startPos;
            filePkgStruct.end = recePkgEndNum;
            filePkgStruct.endPos = position;

            recePkgStartNum = pkgNum;
            recePkgEndNum = pkgNum;
            startPos = startPos;
            endPos = endPos;
            this->sortUnRecePkgList(filePkgStruct);
        } else if (pkgNum - recePkgEndNum == 1)
        {
            recePkgEndNum = pkgNum;
        }  else {

            if (pkgNum - recePkgStartNum >= 0 && pkgNum - recePkgEndNum <= 0)
            {
                //如果收到的包在前面收到包的范围之内，证明此包是重覆的，须hadReceCount--，
                //因为后面有hadReceCount++
//                qDebug() << "pkgNum - recePkgStartNum > 0";
                hadReceCount--;
            } else if (pkgNum - recePkgStartNum == -1)
            {
                //如果收到的包是在小于开始包号1，则修改开始包号
                recePkgStartNum = pkgNum;
            } else if (pkgNum - recePkgStartNum < -1)
            {
                //如果收到的包是在小于开始包号超过1，则证明有包开始丢失，先将收到包的区间从
                //未收到包区间中划分出去
                FilePkgStruct filePkgStruct;
                filePkgStruct.start = recePkgStartNum;
                filePkgStruct.end = recePkgEndNum;
                filePkgStruct.startPos = position;

                recePkgStartNum = pkgNum;
                recePkgEndNum = pkgNum;
                startPos = startPos;
                endPos = endPos;
                this->sortUnRecePkgList(filePkgStruct);
            } else {
                hadReceCount--;
            }
        }
    }
    hadReceCount++;
}

/*******************************************
  功能：得到未收到包的区间列表
  参数：
  返回值：未收到包的区间列表
  ******************************************/
QList<FilePkgStruct> RecePkgManage::getunRecePkgList()
{
//    qDebug() << "getunRecePkgList>>>>" << recePkgStartNum << recePkgEndNum;
    if (recePkgStartNum != 0 || recePkgEndNum != 0)
    {
        FilePkgStruct filePkgStruct;
        filePkgStruct.start = recePkgStartNum;
        filePkgStruct.startPos = startPos;
        filePkgStruct.end = recePkgEndNum;
        filePkgStruct.endPos = endPos;

        recePkgStartNum = 0;
        recePkgEndNum = 0;
        this->sortUnRecePkgList(filePkgStruct);
    }

    return unRecePkgList;

}


/*******************************************
  功能：得到未接收区间的数据
  参数：
  返回值：未接收区间的数据
  ******************************************/
int RecePkgManage::getUnRecePkgListCount() const
{
    return unRecePkgList.count();
}

/*******************************************
  功能：得到未接收区间的
  参数：
  返回值：收到包的数量
  ******************************************/
int RecePkgManage::getRecePkgCount() const
{
    return hadReceCount;
}

/*******************************************
  功能：初始化，设置未接收包区间列表和未接收的包
  参数：list，未接收包区间列表;count，包总数
  返回值：
  ******************************************/
bool RecePkgManage::initRecePkgManage(const int count, const QList<FilePkgStruct> &list)
{
    if (count <= 0)
    {
        return false;
    }
    unRecePkgList.clear();
    unRecePkgList = list;
    pkgCount = count;

    return true;
}


/*******************************************
  功能：初始化,设置包总数，开始要先设置总数后，然后就可以开始添加收到的包编号
  参数：count，包总数
  返回值：
  ******************************************/
bool RecePkgManage::initRecePkgManage(int count)
{
    if (count <= 0 || pkgCount != 0)
    {
        return false;
    }

    pkgCount = count;

    FilePkgStruct filePkgStruct;
    filePkgStruct.start = 1;
    filePkgStruct.end = count;
    filePkgStruct.startPos = 1;
    filePkgStruct.endPos = 1;

    unRecePkgList.clear();
    unRecePkgList.append(filePkgStruct);
    return true;
}

/*******************************************
  功能：未接收包列表排序
  参数：recePkgStruct，未接收包结构体
  返回值：
  ******************************************/
void RecePkgManage::sortUnRecePkgList(const FilePkgStruct &recePkgStruct)
{
//    qDebug () << "recePkgStruct===>" << recePkgStruct.start << recePkgStruct.end;
    if (recePkgStruct.start > recePkgStruct.end)
    {
        return;
    }

    FilePkgStruct filePkgStruct;

    int startNum = 0;       //收到包区间区间 开始线在 未收到包区间的位置
    int endNum = 0;         //收到包区间区间 结束线在 未收到包区间的位置

    //收到包区间结束线是否已经处理的标志
    bool isEndProcess = false;

    //将收到的包的区间从未收到包的区间中分离出去
    //思路：先找到 收到的包的区间开始线 的位置，如果在一个未收到包区间的中间的话，必须将此区间内的
    //已收到包的区间划分出去，记录此个区间的号码
    //然后再找出 收到的包的区间开始线结束线 的位置，思路一样

    for(int i = 0; i < unRecePkgList.count(); i++)
    {
        filePkgStruct = unRecePkgList.at(i);

        if (filePkgStruct.start >= recePkgStruct.start)
        {
            if (filePkgStruct.start == recePkgStruct.start)
            {
                endNum = i;
//                qDebug() << "bbb===================>";
            } else {
                if (i != 0)
                {
                    //i-1的结束大于等于收到包区间的开始
                    if (unRecePkgList[i-1].end >= recePkgStruct.start)
                    {
                        if (unRecePkgList[i-1].end == recePkgStruct.start)
                        {
                            //i-1的结束等于收到包区间的开始
                            endNum = i;
                            unRecePkgList[i-1].end--;
//                            qDebug() << "aaaa==========>" << unRecePkgList[i-1].start << unRecePkgList[i-1].end;
                        } else {
                            if (unRecePkgList[i-1].end < recePkgStruct.end)
                            {
                                //i-1的结束小于收到包区间的结束
                                unRecePkgList[i-1].end = recePkgStruct.start - 1;
//                                qDebug() << "222=====>" << unRecePkgList[i-1].start << unRecePkgList[i-1].end;
                            } else if (unRecePkgList[i-1].end == recePkgStruct.end)
                            {
                                //i-1的结束等于收到包区间的结束
                                unRecePkgList[i-1].start = recePkgStruct.start - 1;
//                                qDebug() << "333=====>" << unRecePkgList[i-1].start << unRecePkgList[i-1].end;

                            }else if (unRecePkgList[i-1].end > recePkgStruct.end)
                            {
                                //i-1的结束大于收到包区间的结束
                                FilePkgStruct filePkgStruct1;
                                filePkgStruct1.start = recePkgStruct.end + 1;
                                filePkgStruct1.end = unRecePkgList[i-1].end;
                                filePkgStruct1.startPos = unRecePkgList[i-1].endPos;
                                filePkgStruct1.endPos = endPos;

//                                qDebug() << "444=====>" << filePkgStruct1.start << filePkgStruct1.end;

                                unRecePkgList[i-1].end = recePkgStruct.start - 1;
                                unRecePkgList.insert(i, filePkgStruct1);
                                i++;
                                endNum = i;
                                isEndProcess = true;
                            }
                        }
                    }
                }
            }
            startNum = i;
            break;
        } else {
            if (unRecePkgList.at(i).end >= recePkgStruct.start)
            {
                if (unRecePkgList.at(i).end > recePkgStruct.end)
                {
                    FilePkgStruct filePkgStruct1;
                    filePkgStruct1.start = recePkgStruct.end + 1;
                    filePkgStruct1.end = unRecePkgList[i].end;
                    filePkgStruct1.startPos = recePkgStruct.endPos;
                    unRecePkgList[i].end = recePkgStruct.start - 1;
                    unRecePkgList.insert(i+1, filePkgStruct1);
                    i++;
                    isEndProcess = true;
//                    qDebug() << isEndProcess << unRecePkgList.count() << i <<  "555=====>" << filePkgStruct1.start << filePkgStruct1.end;

                } else {
                    unRecePkgList[i].end = recePkgStruct.start - 1;
                    unRecePkgList[i].endPos = recePkgStruct.startPos;
                    isEndProcess = true;
//                    qDebug() << i << "666=====>" << unRecePkgList[i].start << unRecePkgList[i].end;
                }
                startNum = i;
                break;
            }
        }
    }


    //如果前面的 收到包区间 的结束线没处理的话，在这边开始处理
    if (!isEndProcess)
    {
        for(int i = startNum; i < unRecePkgList.count(); i++)
        {
            filePkgStruct = unRecePkgList.at(i);

            //先找到结束标志大于 此结束线的位置，然后看是否在这个未收到包区间的中间，
            //如果是则此覆盖的区间分离出去
            if (filePkgStruct.end > recePkgStruct.end)
            {
                if (filePkgStruct.start <= recePkgStruct.end)
                {
                    unRecePkgList[i].start = recePkgStruct.end + 1;
                    unRecePkgList[i].startPos = recePkgStruct.endPos;
                }
                endNum = i;
                break;
            } else {
                endNum = unRecePkgList.count();
            }
        }
//      qDebug() << "startNum===>" << startNum << endNum << unRecePkgList.count();
        //最后将收到包的区间从列表中删除
        int j = startNum;
        if (endNum >= startNum)
        {
            for(int i = startNum; i < endNum; i++)
            {
                unRecePkgList.removeAt(i);
                i--;
                endNum--;
            }
        }
    }


}
